/*
 * Course:    CS 590 Web Services
 * Semseter:  Spring 2009
 * Professor: Sedlemeyer
 * Project:   CHEAT (Code Help Educational Assignment Tool)
 * Due Date:  May 1, 2009
 * Team:      Sarcasm
 *            (Baker, Jason; Mitchell, Robin; Shie, Keith)
 */

package edu.ipfw.cs590.cheat.services;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.w3c.dom.Document;
import org.web_cat._1_0.assignment_sharing.Assignment;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Container to allow the EJB server layer to pass a non-Serializable assignment
 * (derived from the assignment sharing XML schema via JAXB).
 *
 * <p>The bytes of the XML representation of the assignment are placed into this container.<p>
 * <p>Users of this class can then access the original assignment as either:<ul>
 * <li>bytes[],</li>
 * <li>XML DOM, or</li>
 * <li>assignment object graph.</li></ul></p>
 * 
 * @author Keith Shie
 */
public class AssignmentWrapper implements Serializable {

 static private JAXBContext jCtx = null;

  private byte[] assignmentXML;


  /**
   * Contructor
   * @param assignmentXML The bytes of the XML representation of the assignment.
   */
  public AssignmentWrapper( byte[] assignmentXML ) {
    this.assignmentXML = assignmentXML;
  }


  /**
   * Get the bytes of the XML representation of the assignment.
   *
   * @return The bytes of the XML representation of the assignment.
   */
  public byte[] getMeta() {
    return assignmentXML;
  }


  public void setMeta( byte[] meta ) {
    this.assignmentXML = meta;
  }

  static private JAXBContext getJaxbContext() throws JAXBException{
    if ( jCtx == null ){
       jCtx = JAXBContext.newInstance( "org.web_cat._1_0.assignment_sharing" );
    }
    return jCtx;
  }

  /**
   * Extract the assignment object graph.
   * @return assignment as an object graph.
   */
  @SuppressWarnings( "unchecked" )
  public Assignment extractAssignment() {
    Assignment assignment = null;

    if (assignmentXML != null) {
      try {
        JAXBContext jCtx = getJaxbContext();
        final Unmarshaller unmarsh = jCtx.createUnmarshaller();
        final InputStream bais = new ByteArrayInputStream( assignmentXML );
        final JAXBElement<Assignment> asgn = (JAXBElement<Assignment>) unmarsh.unmarshal( new InputSource( bais ) );

        assignment = asgn.getValue();
      } catch (JAXBException ex) {
        Logger.getLogger( AssignmentWrapper.class.getName() ).
                log( Level.SEVERE, ex.getMessage() );
      }
    }

    return assignment;
  }


  /**
   * Extract the DOM representation of the assignment.
   * @return DOM representation of the assignment.
   */
  public Document extractDOM() {
    Document assignment = null;

    if (assignmentXML != null) {
      try {
        final SchemaFactory schFac =
                SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
        Schema assignmentSchema = schFac.newSchema( new URL(
            "http://amethyst.ipfw.edu:8080/cs590-project/assignment-sharing.xsd" ) );
//        final File schemaFile =
//                new File( "../CheatApp/CheatApp-common/xml-resources/jaxb/Assignment Sharing/amethyst.ipfw.edu_8080/cs590-project/assignment-sharing.xsd" );
//        Schema assignmentSchema = schFac.newSchema( schemaFile );

        final DocumentBuilderFactory docBldFac = DocumentBuilderFactory.newInstance();
        docBldFac.setSchema( assignmentSchema );
        docBldFac.setNamespaceAware( true );
        docBldFac.setCoalescing( true );

        final DocumentBuilder docBld = docBldFac.newDocumentBuilder();

        final ByteArrayInputStream bais = new ByteArrayInputStream( assignmentXML );
        assignment = docBld.parse( bais );
      } catch (ParserConfigurationException ex) {
        Logger.getLogger( AssignmentWrapper.class.getName() ).log( Level.SEVERE, ex.getMessage(), ex );
      } catch (SAXException ex) {
        Logger.getLogger( AssignmentWrapper.class.getName() ).log( Level.SEVERE, ex.getMessage(), ex );
      } catch (IOException ex) {
        Logger.getLogger( AssignmentWrapper.class.getName() ).log( Level.SEVERE, ex.getMessage(), ex );
      }
    }

    return assignment;
  }
}
